package org.example.thread2.login;

/**
 * 模拟的登陆 HttpServlet。
 * 实际中 Servlet 与 Spring MVC 都是单例。下面用单例默认模拟 servlet 单例
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2022/12/27 15:47
 */
public class LoginServlet {
    /**
     * 当对象是单例时，成员变量是需要考虑线程安全的，千万不能滥用。而方法中的局部变量是不受多线程影响的.
     */
    private String userName;
    private String password;

    private LoginServlet() {
        //内部类方式实现单例模式步骤 1：私有化构造器
    }

    private static final class Factory {
        //内部类方式实现单例模式步骤 2：静态内部类维护单例，类一加载则已经创建
        private static LoginServlet instance = new LoginServlet();
    }

    public static LoginServlet getInstance() {
        //内部类方式实现单例模式步骤 3：提供静态方法供调用.
        return Factory.instance;
    }

    public void doPost(String userName, String password) {
        //局部变量自然不受多线程影响，大家相互隔离，所以这里的输出是正确的
        System.out.println(userName + "," + password + "\t" + this);
        this.userName = userName;
        this.password = password;
        try {
            //假设用户 a 登陆的时候，这里模拟耗时操作
            String temp = "a";
            if (temp.equals(this.userName)) {
                Thread.sleep(1000);
            }
            //显然并发环境下，这里输出是有问题的.
            System.out.println(this.userName + " = " + this.password);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}